<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>ccbft能力地图展示</title>
    <style type="text/css">
        html, body {
            margin: 0;
            height: 100%;
        }

        canvas {
            display: block;
        }

    </style>
</head>
<body onload="draw();">

</body>
<script src="js/three.js"></script>
<script src="js/GLTFLoader.js"></script>
<script src="js/OrbitControls.js"></script>
<script src="js/stats.min.js"></script>
<script src="js/dat.gui.min.js"></script>
<script>
    var renderer, camera, scene, gui, stats, ambientLight, directionalLight, control;
    var group1 = new THREE.Group();
    group1.name = "AI";

    var group2 = new THREE.Group();
    group2.name = "BlockChain";

    var group3 = new THREE.Group();
    group3.name = "CloudComputing";

    var group4 = new THREE.Group();
    group4.name = "BigData";

    var group5 = new THREE.Group();
    group5.name = "ICDP";

    var group6 = new THREE.Group();
    group6.name = "PublicServ";

    var group7 = new THREE.Group();
    group7.name = "Security";

    var group8 = new THREE.Group();
    group8.name = "DistributedComputing";

    var group3rd = new THREE.Group();
    group3rd.name = "ThirdTitle"


    function initRender() {
        renderer = new THREE.WebGLRenderer({antialias: true});
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.setClearColor('rgb(135,206,250)',1.0);

        //告诉渲染器需要阴影效果
        renderer.shadowMap.enabled = true;
        renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 默认的是，没有设置的这个清晰 THREE.PCFShadowMap
        document.body.appendChild(renderer.domElement);
    }

    function initCamera() {
        camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 10, 1000);
        camera.position.set(0, 100, 200);
        camera.lookAt(new THREE.Vector3(0, 0, 0));
    }

    function initScene() {
        scene = new THREE.Scene();

        scene.background = new THREE.Color(0xf0f0f0)
        // let axesHelper = new THREE.AxesHelper(50)
        // scene.add(axesHelper)
    }

    function initGui() {
        //声明一个保存需求修改的相关数据的对象
        gui = {};

        var datGui = new dat.GUI();
        //将设置属性添加到gui当中，gui.add(对象，属性，最小值，最大值）
    }

    function initLight() {
        ambientLight = new THREE.AmbientLight("#111111");
        scene.add(ambientLight);

        directionalLight = new THREE.DirectionalLight("#ffffff");
        directionalLight.position.set(40, 60, 10);

        directionalLight.shadow.camera.near = 1; //产生阴影的最近距离
        directionalLight.shadow.camera.far = 400; //产生阴影的最远距离
        directionalLight.shadow.camera.left = -50; //产生阴影距离位置的最左边位置
        directionalLight.shadow.camera.right = 50; //最右边
        directionalLight.shadow.camera.top = 50; //最上边
        directionalLight.shadow.camera.bottom = -50; //最下面

        //这两个值决定生成阴影密度 默认512
        directionalLight.shadow.mapSize.height = 1024;
        directionalLight.shadow.mapSize.width = 1024;

        //告诉平行光需要开启阴影投射
        directionalLight.castShadow = true;

        scene.add(directionalLight);
    }

        // 状态显示，包括渲染帧率和显存占用情况
    function initStats() {
        stats = new Stats();
        document.body.appendChild(stats.dom);
    }

    // 轨道控制器，可以使相机围绕目标进行轨道运动
    function initControl() {
        control = new THREE.OrbitControls(camera, renderer.domElement);

    }

    function render() {

        control.update();

        renderer.render(scene, camera);
    }

    function onWindowResize() {

        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);

    }


    var time;
    function animate() {
        // Tween.js
        // //更新控制器
        // render();

        // //更新性能插件
        // stats.update();

        requestAnimationFrame(animate);
        var delta = clock.getDelta();
        // console.log("时间间隔", delta*1000);
        
        for(var i = 0; i < mixers.length; i++) {
            mixers[i].update(delta / 3);

        }

        stats.begin();
        render();
        stats.end();

    }


    function relativePosition(positionIndex) {
        var transferX = 0;
        var transferY = 0;
        var transferZ = 0;
        var group = new THREE.Group();

        // 一级能力文字相对于坐标(0,0,0)的位置
        switch (positionIndex) {
                case 0:
                    transferX = -100    // 一级标题的坐标
                    transferY = 45
                    transferZ = 70
                    px = -110   // 二级标题展示牌中第一块的坐标
                    py = 33
                    pz = 75
                    offsetA = 19    // 二级标题每一块在X轴上的偏移量（补偿）
                    offsetB = -5    // Y轴上的偏移量
                    px2 = -100      // 三级标题展示牌中第一块的坐标
                    py2 = 33
                    pz2 = 75
                    offsetC = 0
                    group = group1
                    arr = arr1
                    break;
                case 1:
                    transferX = -22
                    transferY = 45
                    transferZ = 70
                    px = -28
                    py = 33
                    pz = 75
                    offsetA = 19
                    offsetB = -5
                    px2 = -50
                    py2 = 38
                    pz2 = 75
                    offsetC = -5
                    group = group2
                    arr = arr2
                    break;
                case 2:
                    transferX = 50
                    transferY = 40
                    transferZ = 70
                    px = 40
                    py = 33
                    pz = 75
                    offsetA = 19
                    offsetB = -5
                    group = group3
                    arr = arr3
                    break;
                case 3:
                    transferX = 110
                    transferY = 40
                    transferZ = 70
                    px = 100
                    py = 33
                    pz = 80
                    offsetA = 19
                    offsetB = -5
                    group = group4
                    arr = arr4
                    break;
                case 4:
                    transferX = 110
                    transferY = 50
                    transferZ = -50
                    px = 100
                    py = 43
                    pz = -35
                    offsetA = 19
                    offsetB = -5
                    group = group5
                    arr = arr5
                    break;
                case 5:
                    transferX = 50
                    transferY = 50
                    transferZ = -50
                    px = 40
                    py = 43
                    pz = -35
                    offsetA = 19
                    offsetB = -5
                    group = group6
                    arr = arr6
                    break;
                case 6:
                    transferX = -20
                    transferY = 50
                    transferZ = -50
                    px = -30
                    py = 43
                    pz = -45
                    offsetA = 19
                    offsetB = -5
                    group = group7
                    arr = arr7
                    break;
                case 7:
                    transferX = -100
                    transferY = 50
                    transferZ = -50
                    px = -110
                    py = 43
                    pz = -45
                    offsetA = 19
                    offsetB = -5
                    group = group8
                    arr = arr8
                    break;
        }
        return{
            transferX: transferX,
            transferY: transferY,
            transferZ: transferZ,
            px: px,
            py: py,
            pz: pz,
            offsetA: offsetA,
            offsetB: offsetB,
            px2: px2,
            py2: py2,
            pz2: pz2,
            offsetC: offsetC,
            group: group,
            arr: arr
        }
        
    }




    // 使用BoxGeometry和TextGeometry，通过坐标偏移创建二级能力展示牌
    function createTitle(itemName, position2, group, positionIndex,index) {
        
        // 创建展示牌
        var boxgeo = new THREE.BoxGeometry(18,4,0.1);
        var cubeMaterial = new THREE.MeshBasicMaterial({
            color: 0xFFFFFF
        });
        var cube = new THREE.Mesh(boxgeo, cubeMaterial);
        cube.name = "textContainer_"+positionIndex+"_"+index;
        // console.log(cube.name);
        
        group.add(cube);
        cube.position.x = position2.px;
        cube.position.y = position2.py;
        cube.position.z = position2.pz;

        // 创建文字
        var text = new THREE.FontLoader().load('/fonts/Microsoft YaHei_Regular.json', function(text) {
            var gem = new THREE.TextGeometry(itemName, {
                size: 1.5, //字号大小，一般为大写字母的高度
                height: 1, //文字的厚度
                weight: 'normal', //值为'normal'或'bold'，表示是否加粗
                font: text, //字体，默认是'helvetiker'，需对应引用的字体文件
                style: 'normal', //值为'normal'或'italics'，表示是否斜体
                bevelThickness: 1, //倒角厚度
                bevelSize: 1, //倒角宽度
                curveSegments: 10,//弧线分段数，使得文字的曲线更加光滑
                bevelEnabled: false, //布尔值，是否使用倒角，意为在边缘处斜切
            });
            gem.center();
            var mat = new THREE.MeshBasicMaterial({
                color: 'rgb(28,107,212)',
                // specular: 0x009900,
                // shininess: 10,
                // shading: THREE.FlatShading
            });
            var textObj = new THREE.Mesh(gem, mat);
            textObj.position.x = position2.px;
            textObj.position.y = position2.py;
            textObj.position.z = position2.pz;

            // textobj.rotation.x = 0;
            // textObj.rotation.y = Math.PI * 2;
     
            textObj.castShadow = true;
            textObj.name = "text_"+positionIndex+"_"+index;
            
            
            group.add(textObj);
            // console.log(group2);
            
            // new TWEEN.Tween(textObj.rotation).to({y: Math.PI * 2}, 2000).repeat(Infinity).yoyo(true).start();
        });
        // scene.add(group);
        // console.log(group2);

    }



    function init2ndTitle(items, positionIndex) {

        var px = relativePosition(positionIndex).px;
        var py = relativePosition(positionIndex).py;
        var pz = relativePosition(positionIndex).pz;
        var offsetA = relativePosition(positionIndex).offsetA;
        var offsetB = relativePosition(positionIndex).offsetB;
        var group = relativePosition(positionIndex).group;


        for (let index = 0; index < items.length; index++) {

            const item = items[index];
            if (index % 2 == 0) {
                createTitle(item.text,{
                    px: px,
                    py: py,
                    pz: pz,
                },group,positionIndex,index);
                // px += offsetA;
            } else {
                createTitle(item.text,{
                    px: px+offsetA,
                    py: py,
                    pz: pz,
                },group,positionIndex,index);
                py += offsetB;
            }
            scene.add(group);      
            
        }        
    }

    window.addEventListener("click",onMouseClick,false);
    
    var mouseVector = new THREE.Vector2();
    var raycaster = new THREE.Raycaster();
    function onMouseClick(event) {

        event.preventDefault();                
        x = (event.clientX / window.innerWidth) * 2 - 1;
        y = -(event.clientY / window.innerHeight) * 2 + 1;
        mouseVector.set(x, y);

		raycaster.setFromCamera(mouseVector, camera);
        // group1.traverse(function(obj) {
        //     console.log("group1 entry");
            
        //     for (let i=0;i<12;i++) {
        //         if (obj.name === "textContainer_0_"+i) {
        //             intersects = raycaster.intersectObject(obj);
        //             if (intersects.length > 0) {
        //                 init3rdTitle(arr1, 0, i);
        //                 console.log(obj.name);
                        
        //                 // alert(obj.name);
        //             }
        //         }
        //     }
        // })

        // for (let i=0;i<group2.children.length;i++) {
        //     console.log("here");
            
        //     if (group2.children[i].name === "textContainer_1_"+i) {
        //         var intersects = raycaster.intersectObject(group2.children[i]);
        //         console.log("intersects: " + intersects);
                
        //         if (intersects.length > 0) {
        //             init3rdTitle(arr2,1,i);
        //             console.log(group2.children[i].name);
        //             // return;
                    
        //         }
        //     }
            
        // }

        traverse2(group1,"textContainer_0_",0)
        traverse2(group2,"textContainer_1_",1);

        
        traverse3(group3rd)



        // traverse2(group3rd,"deleteBtn")
        // group2.traverse(function(obj) {
        //     console.log("group2 entry");
            
        //     for (let i=0;i<13;i++) {
        //         if (obj.name === "textContainer_1_"+i) {
        //             intersects = raycaster.intersectObject(obj);
        //             if (intersects.length > 0) {
        //                 init3rdTitle(arr2, 1, i)
        //                 console.log(obj.name);
        //                 return;

        //                 // alert(obj.name);
        //             }
        //         }
        //     }
        // })

        // group3rd.traverse(function(obj) {
        //     console.log("group3rd entry");
            
        //     intersects = raycaster.intersectObject(obj);

        //     if (obj.name === "deleteBtn") {
        //         if (intersects.length > 0) {

        //             group3rd.traverse(function(obj) {
        //                 if (obj.type === 'Mesh') {
        //                     obj.geometry.dispose();
        //                     obj.material.dispose();
        //                     console.log("1111");
                            
        //                 }
        //                 })

        //             scene.remove(group3rd);
        //             return;
        //             // alert(obj.name);
        //         }
        //     }
            
        // })

    }


    function traverse2(group, name, positionIndex) {
        for (let i=0;i<group.children.length;i++) {
            
            if (group.children[i].name === name+i) {
                
                var intersects = raycaster.intersectObject(group.children[i]);
                
                if (intersects.length > 0) {
                    arr = relativePosition(positionIndex).arr
                    init3rdTitle(arr,positionIndex,i);
                    
                    return;
                    
                }
                
            }            
            
        }
    }
    
    function traverse3(group) {
        for (let i=0;i<group.children.length;i++) {
            console.log("aaaa");
            
            if (group.children[i].name === "deleteBtn") {
                console.log("bbb");
                
                var intersects = raycaster.intersectObject(group.children[i]);
                console.log("ccc");
                
                if (intersects.length > 0) {
                    console.log("dddd");
                    
                    // group3rd.traverse(function(obj) {
                    // if (obj.type === 'Mesh') {
                    //     obj.geometry.dispose();
                    //     obj.material.dispose();
                    //     console.log("1111");

                    // }
                    // })
                    deleteObj(group3rd);
                    scene.remove(group3rd);

                        
                }

             
            }

        }

    }

    function deleteObj(group) {
        var obj, i;
        for (i=group.children.length-1;i>=0;i--) {
            obj = group.children[i];
            group.remove(obj);
        }
    }
  
    // 创建三级能力展示牌
    function createTitle2(itemName, position2, group, positionIndex) {



        // 创建展示牌
        var boxgeo = new THREE.BoxGeometry(21,4,0.1);
        var cubeMaterial = new THREE.MeshBasicMaterial({
            color: 0xFFFFFF
        });
        var cube = new THREE.Mesh(boxgeo, cubeMaterial);
        // scene.add(cube);
        group.add(cube);
        cube.position.x = position2.px;
        cube.position.y = position2.py;
        cube.position.z = position2.pz;

        // 创建文字
        var text = new THREE.FontLoader().load('/fonts/Microsoft YaHei_Regular.json', function(text) {
            var gem = new THREE.TextGeometry(itemName, {
                size: 1.5, //字号大小，一般为大写字母的高度
                height: 1, //文字的厚度
                weight: 'normal', //值为'normal'或'bold'，表示是否加粗
                font: text, //字体，默认是'helvetiker'，需对应引用的字体文件
                style: 'normal', //值为'normal'或'italics'，表示是否斜体
                bevelThickness: 1, //倒角厚度
                bevelSize: 1, //倒角宽度
                curveSegments: 10,//弧线分段数，使得文字的曲线更加光滑
                bevelEnabled: false, //布尔值，是否使用倒角，意为在边缘处斜切
            });
            gem.center();
            var mat = new THREE.MeshBasicMaterial({
                color: 'rgb(281,107,212)',
                // specular: 0x009900,
                // shininess: 10,
                // shading: THREE.FlatShading
            });
            var textObj = new THREE.Mesh(gem, mat);
            textObj.position.x = position2.px;
            textObj.position.y = position2.py;
            textObj.position.z = position2.pz;

            // textobj.rotation.x = 0;
            // textObj.rotation.y = Math.PI * 2;
     
            textObj.castShadow = true;
            // scene.add(textObj);
            group.add(textObj);
            // new TWEEN.Tween(textObj.rotation).to({y: Math.PI * 2}, 2000).repeat(Infinity).yoyo(true).start();
        });
        
    }

    function init3rdTitle(items, positionIndex, num) {
        
        var px = relativePosition(positionIndex).px2;
        var py = relativePosition(positionIndex).py2;
        var pz = relativePosition(positionIndex).pz2;
        var offsetC = relativePosition(positionIndex).offsetC;
        var group = new THREE.Group();
        // group = relativePosition(positionIndex).group;
        group = group3rd;
        // console.log(items);

        // 创建删除按钮
        var boxdel = new THREE.BoxGeometry(4,4,0.1);
        var boxdelMat = new THREE.MeshBasicMaterial({
            color:0x1FFFFF
        });
        var cubedel = new THREE.Mesh(boxdel,boxdelMat);
        cubedel.position.x = px ;
        cubedel.position.y = py + 5;
        cubedel.position.z = pz ;
        cubedel.name = "deleteBtn";
        group.add(cubedel);
        
        const item = items[num];
        
        for (let i = 0; i < item.text2.length; i++) {

            createTitle2(item.text2[i],{
                px: px,
                py: py,
                pz: pz,
            },group);
            py += offsetC;

        }
        scene.add(group);


          
    }
    

    var mixers = [];
    var clock = new THREE.Clock();
    function initModel() {

        //底部平面
        var planeGeometry = new THREE.PlaneGeometry(300, 200);
        var planeMaterial = new THREE.MeshLambertMaterial({color: 'rgb(199, 237, 219)', side: THREE.DoubleSide});
        var plane = new THREE.Mesh(planeGeometry, planeMaterial);
        plane.rotation.x = -0.5 * Math.PI;
        plane.position.y = -4;
        plane.receiveShadow = true; //可以接收阴影
        scene.add(plane);

        //创建gltf加载器
        var loader = new THREE.GLTFLoader();
        var group = new THREE.Group();
        // 创建人工智能模块
        loader.load('animation/1.gltf', function (gltf) {
            gltf.scene.scale.set(.1,.1,.1);
            gltf.scene.position.x = -100;
            gltf.scene.position.z = 70;
            gltf.scene.castShadow = true;   // 增加阴影
            scene.add(gltf.scene);
            // group = relativePosition(0).group;
            createText("人工智能",0);

            // 调用动画
            var mixer = new THREE.AnimationMixer( gltf.scene.children[0] ); 
            // console.log(gltf.scene.children[0]);
            mixer.clipAction( gltf.animations[0] ).setDuration( 1 ).play();
            mixers.push( mixer );

        });


        // 区块链模块
        loader.load('animation/1.gltf', function (gltf) {
            gltf.scene.scale.set(.1,.1,.1);
            gltf.scene.position.x = -20;
            gltf.scene.position.z = 70;
            scene.add(gltf.scene);
            createText("区块链",1);
            // 调用动画
            var mixer = new THREE.AnimationMixer( gltf.scene.children[0] );             
            mixer.clipAction( gltf.animations[0] ).setDuration( 1 ).play();
            mixers.push( mixer );
        });
        // 云技术模块
        loader.load('gltf/6.gltf', function (gltf) {
            gltf.scene.scale.set(.1,.1,.1);
            gltf.scene.position.x = 50;
            gltf.scene.position.z = 70;
            scene.add(gltf.scene);
            createText("云计算",2);
        });
        loader.load('gltf/cloud.gltf', function (gltf) {
            gltf.scene.scale.set(.1,.1,.1);
            gltf.scene.position.x = 50;
            gltf.scene.position.y = 20;
            gltf.scene.position.z = 70;
            scene.add(gltf.scene);
            // createText("云计算",2);
        });
        loader.load('animation/7.gltf', function (gltf) {
            gltf.scene.scale.set(.1,.1,.1);
            gltf.scene.position.x = 50;
            gltf.scene.position.y = 20;
            gltf.scene.position.z = 70;
            scene.add(gltf.scene);
            createText("云计算",2);
            // 调用动画
            var mixer = new THREE.AnimationMixer( gltf.scene.children[0] );             
            mixer.clipAction( gltf.animations[0] ).setDuration( 1 ).play();
            mixers.push( mixer );
        });
        // 大数据模块
        loader.load('animation/2.gltf', function (gltf) {
            gltf.scene.scale.set(.1,.1,.1);
            gltf.scene.position.x = 110;
            gltf.scene.position.z = 70;
            scene.add(gltf.scene);
            createText("大数据",3);
            // 调用动画
            var mixer = new THREE.AnimationMixer( gltf.scene.children[0] ); 
            // console.log(gltf.scene.children[0]);
            mixer.clipAction( gltf.animations[0] ).setDuration( 1 ).play();
            mixers.push( mixer );
        });
        // 分布式计算模块
        loader.load('gltf/4.gltf', function (gltf) {
            gltf.scene.scale.set(.2,.2,.2);
            gltf.scene.position.x = 110;
            gltf.scene.position.y = 30;
            gltf.scene.position.z = -50;
            scene.add(gltf.scene);
            createText("分布式计算", 4);
        });

        // 安全技术模块
        loader.load('gltf/4.gltf', function (gltf) {
            gltf.scene.scale.set(.2,.2,.2);
            gltf.scene.position.x = 50;
            gltf.scene.position.y = 30;
            gltf.scene.position.z = -50;
            scene.add(gltf.scene);
            createText("安全技术", 5);
            // 调用动画
            // var mixer = new THREE.AnimationMixer( gltf.scene.children[0] ); 
            // console.log(gltf.scene.children[0]);
            // mixer.clipAction( gltf.animations[0] ).setDuration( 1 ).play();
            // mixers.push( mixer );
        });
        // 公共服务模块
        loader.load('gltf/5.gltf', function (gltf) {
            gltf.scene.scale.set(.2,.4,.2);
            gltf.scene.position.x = -20;
            gltf.scene.position.z = -50;
            scene.add(gltf.scene);
            createText("公共服务", 6);
        });
        loader.load('animation/3.gltf', function (gltf) {
            gltf.scene.scale.set(.2,.4,.2);
            gltf.scene.position.x = -20;
            gltf.scene.position.y = 20;
            gltf.scene.position.z = -50;
            scene.add(gltf.scene);
            createText("公共服务", 6);
            // 调用动画
            var mixer = new THREE.AnimationMixer( gltf.scene.children[0] ); 
            // console.log(gltf.scene.children[0]);
            mixer.clipAction( gltf.animations[0] ).setDuration( 1 ).play();
            mixers.push( mixer );
        });
        // 敏捷开发模块
        loader.load('animation/1.gltf', function (gltf) {
            gltf.scene.scale.set(.1,.1,.1);
            gltf.scene.position.x = -100;
            gltf.scene.position.z = -50;
            scene.add(gltf.scene);
            createText("敏捷开发",7);

            // 调用动画
            var mixer = new THREE.AnimationMixer( gltf.scene.children[0] ); 
            // console.log(gltf.scene.children[0]);
            mixer.clipAction( gltf.animations[0] ).setDuration( 1 ).play();
            mixers.push( mixer );
        });

    }


    // // 使用sprite绘制展示牌，文字锯齿化严重，此方案不采纳
    // function createText(groupname, positionIndex) {

    //     //使用画布动态生成文字
    //     let canvas = document.createElement("canvas");
    //     let ctx = canvas.getContext("2d");
    //     ctx.fillStyle = "#ffff00";
    //     ctx.font = "normal 22px Georgia";
    //     ctx.lineWidth = 4;
    //     ctx.fillText(groupname, 0, 50);
    //     let texture = new THREE.Texture(canvas);
    //     texture.needsUpdate = true;
    //     //使用sprite显示文字
    //     let material = new THREE.SpriteMaterial({map:texture, transparent:true});
    //     let textObj = new THREE.Sprite(material);
    //     textObj.scale.set(64, 64, 10);
            
    //     textObj.position.x = relativePosition(positionIndex).transferX;
    //     textObj.position.y = relativePosition(positionIndex).transferY;
    //     textObj.position.z = relativePosition(positionIndex).transferZ;

 
    //     scene.add(textObj);
    // }



    // 绘制一级能力标题文字
    function createText(title, positionIndex) {
        var group = new THREE.Group();
        group = relativePosition(positionIndex).group;
        var text = new THREE.FontLoader().load('/fonts/Microsoft YaHei_Regular.json', function(text) {
            var gem = new THREE.TextGeometry(title, {
                size: 4, //字号大小，一般为大写字母的高度
                height: 1, //文字的厚度
                weight: 'normal', //值为'normal'或'bold'，表示是否加粗
                font: text, //字体，默认是'helvetiker'，需对应引用的字体文件
                style: 'normal', //值为'normal'或'italics'，表示是否斜体
                bevelThickness: 1, //倒角厚度
                bevelSize: 1, //倒角宽度
                curveSegments: 10,//弧线分段数，使得文字的曲线更加光滑
                bevelEnabled: false, //布尔值，是否使用倒角，意为在边缘处斜切
            });
            gem.center();
            var mat = new THREE.MeshNormalMaterial({
                // color: 'rgb(28,107,212)',
                // specular: 0x009900,
                // shininess: 10,
                // shading: THREE.FlatShading
            });
            var textObj = new THREE.Mesh(gem, mat);
            textObj.transferX = -100;
            textObj.position.x = relativePosition(positionIndex).transferX;
            textObj.position.y = relativePosition(positionIndex).transferY;
            textObj.position.z = relativePosition(positionIndex).transferZ;

            // textobj.rotation.x = 0;
            // textObj.rotation.y = Math.PI * 2;
            textObj.name = "title";
            textObj.castShadow = true;
            group.add(textObj);
            scene.add(group);
            // new TWEEN.Tween(textObj.rotation).to({y: Math.PI * 2}, 2000).repeat(Infinity).yoyo(true).start();
        });
    }




    // // create a test sprite
    // var testSprite;
    // function createSprite() {
    //     testSprite = new THREE.Sprite(new THREE.SpriteMaterial({ color: "green"}));
    //     testSprite.position.set(100,0,0);
    //     testSprite.scale.set(10,10,10);
    //     testSprite.name = "i am sprite";
    //     testSprite.castShadow = true;
    //     scene.add(testSprite);

    //     // window.addEventListener("click",onMouseClick,false);
    //     // window.addEventListener("dblclick",onMouseDblClick,false);
        
        
    // }






    // // 新建一个二维单位向量，根据照相机，把这个向量转换到视点坐标系
    // var mouseVector = new THREE.Vector2();
    // // 射线和模型求交，选中一系列直线
    // var raycaster = new THREE.Raycaster();
    // // 单击事件：通过点击二级能力标题显示出对应三级能力弹窗
    // var timer = null;
    // function onMouseClick(event) {
    //     // console.log("here");
    //     // console.log(group2[1].getObjectByName("text"));

    //     event.preventDefault();        
    //     // 将鼠标位置转换为设备坐标，x和y方向的取之范围是(-1,1)
        
    //     x = (event.clientX / window.innerWidth) * 2 - 1;
    //     y = -(event.clientY / window.innerHeight) * 2 + 1;


    //     mouseVector.set(x, y);

    //     //通过摄像机和鼠标位置更新射线
	// 	raycaster.setFromCamera(mouseVector, camera);

    //     // console.log(group2[1].getObjectByName("text"));
    //     var intersects = raycaster.intersectObject(group2[1].getObjectByName("text"));
    //     console.log(group2[1].getObjectByName("text"));
    //     // console.log(testSprite);
        
    //     console.log('intersects= ' + intersects);
        
    //     clearTimeout(timer);
    //     timer = setTimeout(function() {

       
    //         if (intersects.length > 0) {
                
    //             // console.log(group2[2]);
                
    //             init3rdTitle(arr2,1,3);
    //             // alert("单击事件");

                        
    //         }
    //     },250);

    // }
    




    // 双击事件：关闭三级能力标题弹窗
    function onMouseDblClick(event) {
        event.preventDefault();        
        // 将鼠标位置转换为设备坐标，x和y方向的取之范围是(-1,1)
        x = (event.clientX / window.innerWidth) * 2 - 1;
        y = -(event.clientY / window.innerHeight) * 2 + 1;


        mouseVector.set(x, y);

        //通过摄像机和鼠标位置更新射线
		raycaster.setFromCamera(mouseVector, camera);
        var intersects = raycaster.intersectObject(testSprite);
        // console.log('intersects= ' + intersects);
        
        clearTimeout(timer);

        if (intersects.length > 0) {
            // console.log(group2[3]);
            
            scene.remove(group);
            // scene.remove(group2[3]);
            // alert("双击事件");

                    
        }
    }





    // 能力地图数据
    var arr1 = [
        { text: 'AI平台通用能力',text2: ['特征工程与管理','可视化建模','模型分析/加密/对比','模型评估','模型服务中心','AI-DevOps流水线','服务目录']},
        { text: '算法框架',text2: ['机器学习框架','深度学习框架','国产化深度学习框架','强化学习框架','联邦学习框架'] },
        { text: '数据标注',text2: ['结构化数据标注','图像标注','视频标注','文本标注','语音标注'] },
        { text: '算法平台',text2: ['自动算法选择与模型集成','自动化参数搜索','自动化网络构建','自动特征构造选择'] },
        { text: '计算引擎' },
        { text: '硬件' },
        { text: '智能语音' },
        { text: '计算机视觉' },
        { text: '自然语言处理' },
        { text: '知识图谱' },
        { text: '智能安全' },
        { text: '智能推荐认知决策' },
        ];
    var arr2 = [
        { text: '业务应用组件',text2: ['数字资产','交易溯源','信息存证','数据共享']},
        { text: '钱包',text2: ['热钱包','冷钱包'] },
        { text: 'BaaS平台',text2: ['节点管理','网络管理','合约管理','动态联盟治理','区块链浏览器','云基础设施适配','多底层技术框架适配','统一API'] },
        { text: '共识算法',text2: ['崩溃容错类共识算法','概率性共识算法','拜占庭容错类共识算法','高性能共识算法','自适应共识技术','插件化共识架构'] },
        { text: '智能合约' },
        { text: 'Token经济模型' },
        { text: '数据存储' },
        { text: 'p2p通信' },
        { text: '跨链技术' },
        { text: '可扩展性' },
        { text: '身份认知' },
        { text: '数据安全' },
        { text: '基础框架' },
    ]
    var arr3 = [
        { text: '云原生PaaS'},
        { text: '事务处理（TP）' },
        { text: '分析处理（AP）'},
        { text: '混合事务分析处理' },
    ]
    var arr4 = [
        { text: '数据采集'},
        { text: '数据集成' },
        { text: '数据开发'},
        { text: '智能调度' },
        { text: '数据计算' },
        { text: '数据管理' },
        { text: '数据挖掘' },
        { text: '数据分析与可视化' },
        { text: '数据服务' },
        { text: '数据服务总线' },
        { text: '海量数据存储引擎' },
        { text: '基础资源池化管理' },
        { text: '基础技术灾备' },
        { text: '企业级模型管理' },
    ]
    var arr5 = [
        { text: '服务框架'},
        { text: '中间件体系' },
        { text: '网络与微服务'},
        { text: '管理与监控' },
        { text: '函数计算' },

    ]
    var arr6 = [
        { text: '统一认证'},
        { text: '密码服务' },
        { text: '数据安全'},
        { text: '安全监控' },
        { text: '终端安全' },
        { text: '基础设施安全' },
        { text: '安全运营' },
    ]
    var arr7 = [
        { text: '公共服务平台'},
        { text: '应用功能组件' },
        { text: '技术功能组件'},
        { text: '人工智能功能组件' },
        { text: '安全功能组件' },
        { text: '解决方案' },
    ]
    var arr8 = [
        { text: '协同研发'},
        { text: '知识管理' },
        { text: '代码管理'},
        { text: '设计工具' },
        { text: '开发工具' },
        { text: '测试工具' },
        { text: '部署工具' },
        { text: '制品管理' },
        { text: '流水线' },
    ]



    function draw() {
        initGui();
        initRender();
        initScene();
        initCamera();
        initLight();
        initModel();
        initStats();
        initControl();

        // createSprite();

        init2ndTitle(arr1,0);
        init2ndTitle(arr2,1);
        // init2ndTitle(arr3,2);
        // init2ndTitle(arr4,3);
        // init2ndTitle(arr5,4);
        // init2ndTitle(arr6,5);
        // init2ndTitle(arr7,6);
        // init2ndTitle(arr8,7);

        animate();
        window.onresize = onWindowResize;
    }
</script>
</html>